iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0
Software Development

從零開始學Python系列 第 21

[Day 21] 從零開始學Python - 基本圖形處理Pillow:花下是誰對影成雙

  • 分享至 

  • xImage
  •  

註:本文同步刊載在Medium,若習慣Medium的話亦可去那邊看呦!

我們先來解昨天的練習吧!
我們整理一下三種解的寫法,並且分別改名成cs1, cs2, cs3,
那麼計算時要注意的有:

  1. 為了確保有在運行,我們多加一個print(),可以自行拿掉。
  2. cs2記得要給起始的字典,當然也可以直接在(n, dic)這邊給入也行。
  3. 記得下globals=globals()。
import timeit

def cs1(n):
    if n == 1 or n == 2:
        return n
    return cs1(n-1) + cs1(n-2)
    
def cs2(n, dic):
    if n in dic:
        return dic[n]
    dic[n] = cs2(n-1, dic) + cs2(n-2, dic)
    return dic[n]

# dic = {1 : 1, 2 : 2} # 這個應該要放到setup裡

import functools
@functools.lru_cache(maxsize=None)
def cs3(n):
    if n == 1 or n == 2:
        return n
    return cs3(n-1) + cs3(n-2)

print(timeit.timeit('print(cs1(35))', globals=globals(), number=10))
print()
print(timeit.timeit('print(cs2(35, dic))', setup='dic = {1 : 1, 2 : 2}', globals=globals(), number=10)) 
print()
print(timeit.timeit('print(cs3(35))', setup='import functools', globals=globals(), number=10)) 

接下來我們來講基本的影像處理。
PIL(Python Imaging Library)是一套影像處理的模組,
可以做到一些常見的影像處理和操作,
比如裁切、平移、旋轉、縮放,
調整亮度、色調,套用濾鏡等等,
雖然是沒有專業的Photoshop(免費的有GIMP)等軟體厲害,
但勝在可以在Python中用程式的方式來處理。
但原本的PIL早在Python 2.7後就斷更了,
但後來有一群好心人在這個基礎上開了一個新的版本,
並命名為Pillow,除了支援Python 3.x的版本外,
也加入了一些特性,所以我們這裡只需要安裝Pillow就行啦!
由於不是內建函式庫,請利用安裝Python時,
所附帶pip套件管理程式來安裝Pillow:

pip install Pillow

我們下面使用從pixabay取得的免費圖片
進行接下來的操作(請下載後將圖片放置執行程式的位置):

>>> from PIL import Image
>>> img = Image.open('flower.jpg') # 讀檔
>>> img.format, img.size, img.mode # 圖片格式,寬高,RGB彩色
('JPEG', (1920, 1280), 'RGB')
>>> img.show() # 會將圖片顯示在螢幕上

https://ithelp.ithome.com.tw/upload/images/20201003/201198716g4Y2YLIXY.jpg

>>> img_rotate = img.rotate(180) # 將圖片順時針轉180度
>>> img_rotate.show() # 再顯示,應該會看到倒過來的花瓶
# 要裁切請用crop, 並且必須傳入Tuple,4個數分別代表左上(x1, y1)/右下(x2, y2)
# 在一般程式的圖形處理中,原點(0, 0)在左上角
# 往右代表x增加,往下代表y增加,留意和一般座標的定法不同!
>>> img_crop = img_rotate.crop((960, 50, 1920, 1080))
>>> img_crop.show() # 將旁邊的空白修掉了一點,再來看看結果
# 按照決定的寬高來縮放調整圖片大小,同樣需要以Tuple表示
>>> img_resize = img_crop.resize((240, 250))
>>> img_crop.save('crop.jpg')
>>> img_res = img_resize.rotate(180) # 再轉過來
>>> img_res.save('res.bmp') # 存到檔案,格式依照副檔名決定。
# 將img_res的內容貼到img_rotate上,並合成一張(當然還是要save過後才能看到改變)
>>> img_rotate.paste(img_res, (0, 0))
>>> img_rotate.show()
>>> img_rotate.save('combination.png')

最後的結果應該如下:
https://ithelp.ithome.com.tw/upload/images/20201003/20119871Qb8Gy3W9US.png
上面我們簡單的使用了幾個屬性和方法:
format/size/mode(顯示格式/大小/色彩模式)
show/rotate/crop/paste/save(顯示圖片/旋轉/裁切/貼上/存檔)
其他還有像是filter(濾鏡,在ImageFilter模組裡)可以作一些基本的特效,
讀者有興趣可以再查找相關的方法嘗試。

接下來,我們再來看看其他有趣的功能。
假設今天我們想要製作簡單的長輩圖,
(以原來的flower.jpg為例,其寬高為1920及1280)
那我們需要Pillow裡面關於繪圖的模組來進行操作,
該模組名為ImageDraw,
可以用來處理繪製各種常見圖形,以及文字的方法。
同時,由於一般的文字字型會有不能處理中文的問題,
我們這邊會直接引入truetype的中文字型,
讀者可以從C:\Windows\Fonts選擇一個喜歡的字型,
並將其複製到你所使用的資料夾以利操作。
我們下面會以複製"微軟正黑體"為例,
複製到資料夾後會看到三個變形的字體,
分別是msjh.ttc, msjhl.ttc, msjhbd.ttc,
我們接下來選擇當中的msjhbd.ttc(粗體字型)進行操作。

>>> from PIL import Image, ImageDraw, ImageFont
# 如果要用空白畫布來繪製,可以用Image.new("RGB", (400,300))的形式建立。
>>> img = Image.open('flower.jpg')
# copy可以用來複製一個Image物件,先備份一下,不行就拿它來蓋掉img
>>> backup_img = img.copy()
>>> backup_img.show()
# 建立一個Draw物件,接下來draw所有的操作都會影響到img上面。
>>> draw = ImageDraw.Draw(img)
>>> font = ImageFont.truetype('./msjhbd.ttc', 100) # 給定字型及大小
>>> text = '霹靂卡霹靂拉拉 波波力那貝貝魯多'
>>> draw.text( (960, 320), text, font=font) # 好像太大了?
>>> img.show()
>>> font = ImageFont.truetype('./msjhbd.ttc', 50) # 改一下大小
>>> draw.text( (960, 320), text, font=font) # 再畫一次(應該會重複)
>>> img.show()
>>> img = backup_img.copy() # 洗掉吧!
>>> draw = ImageDraw.Draw(img) # 蓋回來會影響到draw跟img的連結,所以要重置
>>> draw.ink = 0xff0000 # 我們可以更改要使用的顏色(0x代表16進位)
>>> draw.text( (960, 320), text, font=font)
>>> img.show() # 看起來應該是藍色
# 也可以使用fill參數代入,順序是RGBA,也就是紅、綠、藍、透明度(alpha)
>>> draw.text( (1060, 960), '認同請分享', font=font, fill=(255,0,0,128))
>>> img.show()
# 正式來囉!關於顏色的選擇可以使用如htmlcolorcodes等網站來取得色碼
>>> img = backup_img.copy()
>>> draw = ImageDraw.Draw(img)
>>> font = ImageFont.truetype('./msjhbd.ttc', 60)
>>> draw.ink=0xF39C12
# draw.text()可以多行
>>> text = '請常唸\n\n  霹靂卡霹靂拉拉\n  波波力那貝貝魯多\n\n唸時\n須心無雜念 專注 便可心想事成'
>>> draw.text( (1000, 300), text, font=font)
>>> font = ImageFont.truetype('./msjhbd.ttc', 70)
>>> draw.text( (1520, 960), '認同請分享', font=font, fill=(165, 105, 189, 0))
>>> img.show()
>>> img.save('elder.jpg') # 送給長輩吧XD!

結果應該會像這樣:
https://ithelp.ithome.com.tw/upload/images/20201003/20119871B5kt3I4lJE.jpg

除了文字以外,當然也可以畫一些像是點、線、矩形、橢圓等幾何圖形,
讀者可以再參照Pillow的ImageDraw模組的說明文件

今天的練習的部分,
請嘗試運用今天提到的部分,
幫筆者設計一個宣傳長輩圖XD!
例如:
「請常唸
從LeetCode學演算法 基礎打底 進階扎實 面試通靈
選購全套享優惠 居家旅行 通過面試 必備良藥
              認同請分享」
歡迎貼到留言區讓大家看看你的設計XD!

那麼,我們就明天見囉!


上一篇
[Day 20] 從零開始學Python - 時間量測與效率檢驗:你的時間也不是你的時間
下一篇
[Day 22] 從零開始學Python - 圖形化使用者介面Tkinter:直到現在,我還默默的等待
系列文
從零開始學Python30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言